package edu.cicese.tm;

import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
import com.sun.awt.AWTUtilities;
import com.toedter.calendar.JCalendar;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import javax.swing.ButtonGroup;
import javax.swing.ComboBoxModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 15/03/11
 * Time: 08:09 AM
 */
public class DialogNotificationType extends JDialog{

	private FrameTagCreation frmTagCreation;
	private FrameTagEdition frmTagEdition;
	private JPanel pCalendar;
	private JRadioButton rbAllways, rbPeriodic, rbSpecific, rbTimeAllways, rbTimeSpecific;
	private JCheckBox[] chbDays;
	private JCheckBox chbAllDays;
	private JCalendar calendar;
	private JComboBox cbStartingTime, cbEndingTime;
	private JLabel lblDate;

	private String[] hours = new String[] {
			"00:00", "00:30", "01:00", "01:30", "02:00", "02:30", "03:00", "03:30",
			"04:00", "04:30", "05:00", "05:30", "06:00", "06:30", "07:00", "07:30",
			"08:00", "08:30", "09:00", "09:30", "10:00", "10:30", "11:00", "11:30",
			"12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30",
			"16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00", "19:30",
			"20:00", "20:30", "21:00", "21:30", "22:00", "22:30", "23:00", "23:30"
	};

	public DialogNotificationType(FrameTagCreation owner, String date) {
		super(owner);
		frmTagCreation = owner;
		AWTUtilities.setWindowOpacity(frmTagCreation, 0.75f);
		initiateComponenets(date);
	}

	public DialogNotificationType(FrameTagEdition owner, String date) {
		super(owner);
		frmTagEdition = owner;
		AWTUtilities.setWindowOpacity(frmTagEdition, 0.75f);
		initiateComponenets(date);
	}

	//! Creates GUI components
	public void initiateComponenets(String date) {
		setLayout(null);
		setTitle("Programación de notifiación");
		setSize(485, 280);
		setIconImage(new ImageIcon(getClass().getClassLoader().getResource("icons/icon.png")).getImage());
		setResizable(false);
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				closeWindow(false);
			}
		});

		// NOTIFICATION TYPE
		JPanel pRadioButtons = new JPanel();
		pRadioButtons.setLayout(null);
		pRadioButtons.setBorder(new TitledBorder("Tipo"));
		pRadioButtons.setBounds(5, 0, 90, 90);
		rbAllways = new JRadioButton();
		SwingUtil.addRadioButton(rbAllways, 10, 18, 75, 20, "Siempre", pRadioButtons);
		rbAllways.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				typeChanged();
			}
		});
		rbAllways.setSelected(true);
		rbPeriodic = new JRadioButton();
		SwingUtil.addRadioButton(rbPeriodic, 10, 40, 75, 20, "Periódica", pRadioButtons);
		rbPeriodic.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				typeChanged();
			}
		});
		rbSpecific = new JRadioButton();
		SwingUtil.addRadioButton(rbSpecific, 10, 62, 75, 20, "Específica", pRadioButtons);
		rbSpecific.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				typeChanged();
			}
		});
		ButtonGroup bgType = new ButtonGroup();
		bgType.add(rbAllways);
		bgType.add(rbPeriodic);
		bgType.add(rbSpecific);

		// PERIODIC NOTIFICATION
		JPanel pPeriodic = new JPanel();
		pPeriodic.setLayout(null);
		pPeriodic.setBorder(new TitledBorder("Periódica"));
		pPeriodic.setBounds(100, 0, 160, 150);
		String[] days = new String[] {
			"Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"
		};
		chbDays = new JCheckBox[7];
		int posY = 18, posX = 7;
		for (int i = 0; i < 7; i++, posY += 22) {
			if (i == 4) {
				posX = 82;
				posY = 18;
			}
			chbDays[i] = new JCheckBox(days[i]);
			SwingUtil.addCheckBox(chbDays[i], posX, posY, 75, 20, pPeriodic, null);
			chbDays[i].addChangeListener(new ChangeListener() {
				public void stateChanged(ChangeEvent e) {
					daysChanged();
				}
			});
		}
		JLabel lblDivider = new JLabel();
		SwingUtil.addLabel(lblDivider, 7, posY + 25, 152, 4, "------------------------------", pPeriodic, null);
		lblDivider.setForeground(Color.LIGHT_GRAY);
		chbAllDays = new JCheckBox("Todos");
		SwingUtil.addCheckBox(chbAllDays, 7, posY + 36, 75, 20, pPeriodic, null);
		chbAllDays.setSelected(true);
		chbAllDays.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				if (chbAllDays.isSelected()) {
					selectAllDays();
				}
			}
		});

		// SPECIFIC NOTIFICATION
		pCalendar = new JPanel();
		pCalendar.setLayout(null);
		pCalendar.setBorder(new TitledBorder("Fecha específica"));
		pCalendar.setBounds(265, 0, 210, 178);
		lblDate = new JLabel();
		SwingUtil.addLabel(lblDate, 137, 151, 100, 20, "", pCalendar, null);
		lblDate.setFont(new Font("Segoe UI", Font.BOLD, 12));
		lblDate.setForeground(Color.BLUE);
		calendar = new JCalendar();
		calendar.setBounds(5, 20, 200, 155);
		calendar.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent e) {
				SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
				lblDate.setText(df.format(calendar.getCalendar().getTime()));
			}
		});
		pCalendar.add(calendar);
		pCalendar.setComponentZOrder(calendar, 1);
		pCalendar.setComponentZOrder(lblDate, 0);

		// SPECIFIC TIME
		JPanel pTime = new JPanel();
		pTime.setLayout(null);
		pTime.setBorder(new TitledBorder("Hora"));
		pTime.setBounds(100, 150, 160, 100);

		rbTimeAllways = new JRadioButton();
		SwingUtil.addRadioButton(rbTimeAllways, 10, 15, 80, 20, "Todo el día", pTime);
		rbTimeAllways.setSelected(true);
		rbTimeAllways.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				timeTypeChanged();
			}
		});
		rbTimeSpecific = new JRadioButton();
		SwingUtil.addRadioButton(rbTimeSpecific, 10, 35, 120, 20, "Horario específico", pTime);
		rbTimeSpecific.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				timeTypeChanged();
			}
		});
		ButtonGroup bgTimeType = new ButtonGroup();
		bgTimeType.add(rbTimeAllways);
		bgTimeType.add(rbTimeSpecific);

		JLabel lblStartingTime = new JLabel(), lblEndingTime = new JLabel();
		SwingUtil.addLabel(lblStartingTime, 10, 52, 60, 20, "Inicio", pTime, null);
		SwingUtil.addLabel(lblEndingTime, 85, 52, 60, 20, "Fin", pTime, null);

		cbStartingTime = new JComboBox(hours);
		cbStartingTime.setBounds(10, 72, 60, 20);
		cbStartingTime.setSelectedItem("12:00");
		cbStartingTime.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				timeChanged(cbEndingTime.getSelectedItem().toString());
			}
		});
		cbEndingTime = new JComboBox();
		cbEndingTime.setBounds(85, 72, 60, 20);

		pTime.add(cbStartingTime);
		pTime.add(cbEndingTime);

		// BUTTONS
		JPanel pButtons  = new JPanel();
		pButtons.setLayout(null);
		pButtons.setBounds(3, 90, 90, 90);
		JButton btnAccept = new JButton("Aceptar");
		addButton(btnAccept, 2, 10, 80, 32, "Aceptar", "accept", pButtons, null);
		btnAccept.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionAccept();
			}
		});

		JButton btnCancel = new JButton("Cancelar");
		addButton(btnCancel, 0, 42, 90, 32, "Cancelar", "cancel", pButtons, null); //29
	    btnCancel.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
			    actionCancel();
		    }
	    });

		getContentPane().add(pRadioButtons);
		getContentPane().add(pPeriodic);
		getContentPane().add(pCalendar);
		getContentPane().add(pTime);
		getContentPane().add(pButtons);

		Rectangle window = getBounds();
		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation((screen.width - window.width) / 2, (screen.height - window.height) / 2);
		setVisible(true);
		
		selectAllDays();
		timeChanged("24:00");
		selectDate(date);
		typeChanged();
		timeTypeChanged();
	}

	//! Closes the dialog and brings back the FrameTagCreation window
	private void closeWindow(boolean acceptOrCancel) {
		if (acceptOrCancel) {
			setVisible(false);
			dispose();
		}
		if (frmTagCreation != null) {
			frmTagCreation.setEnabled(true);
			frmTagCreation.toFront();
			AWTUtilities.setWindowOpacity(frmTagCreation, 1f);
		}
		else {
			frmTagEdition.setEnabled(true);
			frmTagEdition.toFront();
			AWTUtilities.setWindowOpacity(frmTagEdition, 1f);
		}
	}

	//! Called when the button Accept is clicked. Saves the date selected
	@SuppressWarnings({"unchecked"})
	private void actionAccept() {
		JSONObject joDate = new JSONObject();
		int type = getType();
		joDate.put("type", type);
		if (type != 0) {
			if (type == 1) {
				JSONArray jaDays = new JSONArray();
				for (int i = 0; i < 7; i++) {
					if (chbDays[i].isSelected()){
						jaDays.add(i);
					}
				}
				joDate.put("days", jaDays);
			}
			else {
				joDate.put("date", lblDate.getText());
			}
			int timeType = rbTimeAllways.isSelected() ? 0 : 1;
			joDate.put("timeType", timeType);
			if (timeType == 1) {
				joDate.put("begin", cbStartingTime.getSelectedItem());
				joDate.put("end", cbEndingTime.getSelectedItem());
			}
		}
		if (frmTagCreation != null) {
			frmTagCreation.date = joDate.toJSONString();
			System.out.println(frmTagCreation.date);
		}
		else {
			frmTagEdition.date = joDate.toJSONString();
			System.out.println(frmTagEdition.date);
		}
		closeWindow(true);
	}

	//! Called when the button Cancel is clicked
	private void actionCancel() {
		closeWindow(true);
	}

	//! Adds a JButton
	private void addButton(JButton button, int x, int y, int width, int height,
	                              String toolTipText, String iconName, JPanel pane, Container container) {
		Icon icon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + ".png"));
		Icon rIcon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + "O.png"));
		Icon pIcon = new ImageIcon(getClass().getClassLoader().getResource("icons/" + iconName + "P.png"));
		SwingUtil.addButton(button, x, y, width, height, toolTipText, icon, rIcon, pIcon, pane, container);
	}

	//! Enables/disables the needed components according to the notification type
	private void typeChanged() {
		if (rbAllways.isSelected()) {
			enablePeriodic(false);
			enableSpecific(false);
			enableTimePane(false);
		}
		else {
			enableTimePane(true);
			if (rbPeriodic.isSelected()) {
				enablePeriodic(true);
				enableSpecific(false);
			}
			else {
				enablePeriodic(false);
				enableSpecific(true);
			}
		}
		pCalendar.repaint();
	}

	private int getType() {
		if (rbAllways.isSelected()) {
			return 0;
		}
		else {
			if (rbPeriodic.isSelected()) {
				return 1;
			}
		}
		return 2;
	}

	//! Shows a specific date
	private void selectDate(String date) {
		JSONObject joDate = (JSONObject) JSONValue.parse(date);
		int type = 0;
		if (joDate != null && joDate.get("type") != null) {
			type = Integer.valueOf(joDate.get("type").toString());
		}
		if (type != 0) {
			if (type == 1) {
				rbPeriodic.setSelected(true);
				JSONArray jaDays = (JSONArray) joDate.get("days");
				if (jaDays.size() != 7) {
//					selectAllDays();
//				}
//				else {
					for (int i = 0; i < 7; i++) {
						chbDays[i].setSelected(false);
					}
					for (Object jaDay : jaDays) {
						chbDays[Integer.valueOf(jaDay.toString())].setSelected(true);
					}
				}
			}
			else {
				rbSpecific.setSelected(true);
				SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
				try {
					Date d = df.parse(joDate.get("date").toString());
					System.out.println(d);
					calendar.setDate(d);
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}

			int timeType = Integer.valueOf(joDate.get("timeType").toString());
			if (timeType == 0) {
				rbTimeAllways.setSelected(true);
			}
			else {
				rbTimeSpecific.setSelected(true);
				cbStartingTime.setSelectedItem(joDate.get("begin"));
				timeChanged(joDate.get("end").toString());
			}
		}
	}

	//! Selects every day
	private void selectAllDays() {
		for (JCheckBox chb : chbDays) {
			chb.setSelected(true);
		}
		chbAllDays.setSelected(true);
	}

	//! Deselects the 'All days' box
	private void daysChanged() {
		for (JCheckBox chb : chbDays) {
			if (!chb.isSelected()) {
				chbAllDays.setSelected(false);
				break;
			}
		}
	}

	//! Enables/disables the needed components according to the notification time type
	private void timeTypeChanged() {
		enableTime(!rbTimeAllways.isSelected());
	}

	//! Enables/disables the Periodic Pane
	private void enablePeriodic(boolean state) {
		for (JCheckBox chb : chbDays) {
			chb.setEnabled(state);
		}
		chbAllDays.setEnabled(state);
	}

	//! Enables/disables the Specific Pane
	private void enableSpecific(boolean state) {
		calendar.setEnabled(state);
	}

	//! Enables/disables the Time Pane
	private void enableTimePane(boolean state) {
		rbTimeAllways.setEnabled(state);
		rbTimeSpecific.setEnabled(state);
		timeTypeChanged();
	}

	// Enables/disables the time pickers
	private void enableTime(boolean state) {
		cbStartingTime.setEnabled(state);
		cbEndingTime.setEnabled(state);
	}

	//! Displays the available ending time options according to the notification starting time selected
	private void timeChanged(String endTime) {
		cbEndingTime.removeAllItems();
		for (int i = cbStartingTime.getSelectedIndex() + 1; i < hours.length; i++) {
			cbEndingTime.addItem(hours[i]);
		}

		cbEndingTime.addItem("24:00");
		ComboBoxModel cbModel = cbEndingTime.getModel();
		for (int i  = 0; i < cbModel.getSize(); i++) {
			if (cbModel.getElementAt(i).equals(endTime)) {
				cbEndingTime.setSelectedItem(endTime);
				break;
			}
		}
	}

	public static void main(String[] a) {
		try {
			UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
			UIManager.put("Panel.background", Color.WHITE);
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
//		new DialogNotificationType(null);
	}
}
